#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <string.h>
#include <dlfcn.h>


#define SHM_KEY 1234
#define SHM_SIZE 4096

struct shm_type
{
    char name[10];
    int arg1;
    int arg2;
    int result;
};

int main()
{
    int shmid;
    char *shmaddr;
    pid_t pid;
    struct shm_type shm;

    memset(&shm, 0 ,sizeof(struct shm_type));

    // 创建共享内存段
    if ((shmid = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT | 0666)) == -1) {
        perror("shmget");
        exit(1);
    }

    // 映射共享内存段到进程地址空间
    if ((shmaddr = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

    // fork一个新进程
    pid = fork();
    if (pid < 0) {
        perror("fork");
        exit(1);
    } else if (pid == 0) {
        // 子进程

        usleep(10000);
        struct shm_type t_shm;
        memset(&t_shm, 0 ,sizeof(struct shm_type));
        memcpy(&t_shm, shmaddr, sizeof(struct shm_type));
        //printf("name1: %s\n", t_shm.name);

       // Open the dynamic library
        void* handle = dlopen("./libmylib.so", RTLD_LAZY);
        if (!handle) {
            printf("Failed to open library: %s\n", dlerror());
            return 1;
        }   
    
        // Get a function pointer from the library
        int (*add)(int, int) = dlsym(handle, t_shm.name);
        if (!add) {
            printf("Failed to get function pointer: %s\n", dlerror());
            dlclose(handle);
            return 1;
        }

        printf("Child process: library function called.\n");
        t_shm.result = add(t_shm.arg1, t_shm.arg2);
        printf("result: %d\n", t_shm.result);
        printf("Child process exit.\n");

        // 打开共享内存段中的动态库
        dlclose(handle);

        exit(0);
    } else {
        // 父进程

        memset(shmaddr, 0, SHM_SIZE);
        memcpy(shm.name, "add", sizeof("add"));
        shm.arg1 = 1;
        shm.arg2 = 99;
        memcpy(shmaddr, &shm, sizeof(struct shm_type));

        // 等待子进程结束
        int status;
        waitpid(pid, &status, 0);

        // 解除共享内存段的映射
        shmdt(shmaddr);
        // 删除共享内存段
        shmctl(shmid, IPC_RMID, NULL);
        printf("Parent process exit.\n");
        exit(0);
    }
}
